#pragma once

#include "Types.h"
#include "DLL.h"
#include "Segment.h"
#include "Doc.h"

#include <MyFC/Event.h>

namespace My {

class DLL_API SegmentSet : public EventDispatcher
{
public:
	virtual Doc & GetDoc() = 0;
	virtual bool IsEmpty() const = 0;
	virtual Size GetSegmentCount() const = 0;
	virtual Segment & GetSegment(Size) = 0;
	virtual void EraseSelection() = 0;
	virtual void MoveSelection(int) = 0;
public:
	int GetActiveSegment();
	void SetActiveSegment(int);
	Segment * GetActiveSegmentPtr();
public:
	class Event : public My::Event {
	public:
		SegmentSet &	m_Segments;
		Event(SegmentSet & s) : m_Segments(s) { }
	};
	class Change : public Event {
	public:
		Change(SegmentSet & s) : Event(s) { }
	};
};

template <typename S>
class SegmentUpdate;

template <typename S>
class TypedSegmentSet : public SegmentSet {
	friend class SegmentUpdate<S>;
public:
	typedef S SegmentType;
public:
	virtual void EraseSelection();
	virtual void MoveSelection(int);
protected:
	virtual void Insert(Size, SegmentType *) = 0;
	virtual SegmentType * Erase(Size) = 0;
};

class SegmentSelection : public Selection {
public:
	SegmentSelection(SegmentSet &, int active = -1);
	int GetActive() const
		{ return m_Active; }
	void SetActive(int);
public:
	virtual bool IsEmpty() const;
	virtual void Clear();
	virtual bool Erasable() const;
	virtual void Erase();
	virtual bool Equals(const Selection &) const;
	virtual void BeginUpdate() { }
	virtual void EndUpdate() { }
private:
	SegmentSet &	m_Segments;
	int				m_Active;
};

template <typename S>
class SegmentUpdate {
public:
	typedef S SegmentType;
public:
	SegmentUpdate(TypedSegmentSet<S> &);
	~SegmentUpdate();
public:
	void Insert(Size index, SegmentType *);
	SegmentType * Erase(Size index);
private:
	TypedSegmentSet<S> &	m_Owner;		
	int						m_Active;
	Segment *				m_pActive;
};

} // My

#include "Impl/SegmentSet.inl"
